<template>
  <!-- 预览 -->
  <div class="ant-modal-root preview" :class="className">
    <DraggableContainer :referenceLineColor="'white'">
      <DraggableResizer
        :initW="state.width"
        :initH="state.height"
        v-model:w="state.width"
        v-model:x="state.x"
        v-model:y="state.y"
        v-model:h="state.height"
        :draggable="true"
        :resizable="true"
        tabindex="-1"
        :parent="false"
        :rotatable="false"
        class="ant-modal-wrap1"
        role="dialog"
        style="position: fixed"
      >
        <div role="document" class="img-modal">
          <div class="ant-modal-content">
            <div class="ant-modal-body" style="padding: 0px">
              <header>
                <div class="preview-action pr">
                  <div v-if="type !== 'video'" class="f1 tal">
                    <a-button
                      @click="decline"
                      :disabled="state.previewSize <= 100"
                      size="small"
                      class="mr10"
                    >
                      <template #icon> <MinusOutlined /></template>
                    </a-button>
                    <a-input
                      id="input"
                      ref="inputText"
                      v-model:value="state.previewSize"
                      :maxLength="3"
                      style="width: 100px"
                    />
                    <span class="ml10">%</span>
                    <a-button @click="increase" size="small" class="ml10">
                      <template #icon><PlusOutlined /> </template>
                    </a-button>
                  </div>
                  <div>
                    <a-button
                      type="link"
                      @click="downloadImg(state.fileList[state.activeIndex])"
                      class="mr20"
                      v-if="showDownload && type !== 'video'"
                      >下载
                    </a-button>
                    <span
                      @click.stop="onClose"
                      class="cp pa r-50 t-30 lh-normal"
                    >
                      <CloseCircleOutlined style="font-size: 40px" />
                    </span>
                  </div>
                </div>
              </header>
              <div class="preview_img_wrapper" style="padding: 0 25px">
                <div
                  v-if="state.fileList.length > 1"
                  class="custom-slick-arrow slick-prev"
                  @click="afterChange(-1)"
                >
                  <LeftOutlined />
                </div>
                <div
                  class="view_img_list"
                  style="overflow: hidden; height: 100%"
                >
                  <div
                    class="view_img_item df aic"
                    v-for="(item, index) in props.fileList"
                    :key="item.uid"
                    :class="{
                      active: index === state.activeIndex
                    }"
                  >
                    <video
                      v-if="props.type === 'video' || isVideo(item.ossUrl)"
                      autoplay
                      controls
                      x5-playsinline=""
                      playsinline=""
                      webkit-playsinline=""
                      :id="'video' + index"
                      muted
                      preload="auto"
                      style="width: 100%; height: 100%"
                      :poster="generateVideoPoster(item.ossUrl)"
                    >
                      <source :src="item.ossUrl" />
                      Your browser does not support the video tag.
                    </video>
                    <img
                      v-drag
                      style="margin: auto"
                      :data-size="state.previewSize"
                      v-if="isImage(item.ossUrl)"
                      alt="该文件不支持在线查看，可尝试下载下来查看"
                      :style="{
                        transform: `scale3d(${state.previewSize / 100},${
                          state.previewSize / 100
                        },1)`
                      }"
                      v-lazyLoad="item.ossUrl"
                      data-w="800"
                    />
                  </div>
                </div>
                <div
                  class="custom-slick-arrow slick-next"
                  @click="afterChange(1)"
                  v-if="state.fileList.length > 1"
                >
                  <RightOutlined />
                </div>
              </div>
            </div>
          </div>
          <div
            tabindex="0"
            aria-hidden="true"
            style="width: 0px; height: 0px; overflow: hidden"
          ></div>
        </div>
      </DraggableResizer>
    </DraggableContainer>
  </div>
</template>
<script setup>
import {
  MinusOutlined,
  PlusOutlined,
  CloseCircleOutlined,
  LeftOutlined,
  RightOutlined
} from '@ant-design/icons-vue'
/**
 * 局部引入是为了使用h绘制vnode
 */
import AButton from 'ant-design-vue/lib/button'
import AInput from 'ant-design-vue/lib/input'
import { vLazyLoad } from 'utils/directives.js'
import { reactive, computed } from 'vue'
import { downloadImg } from 'utils/file.js'
import { DraggableResizer, DraggableContainer } from 'vue3-draggable-resizer'

import 'vue3-draggable-resizer/style.css'
import { isImage, isVideo, generateVideoPoster } from 'utils/utils'
const props = defineProps({
  type: {
    type: String,
    default: null
  },
  file: {
    type: Object
  },
  fileList: {
    type: Array,
    default() {
      return []
    }
  },
  visible: {
    type: Boolean,
    default: false
  },
  showDownload: {
    type: Boolean,
    default: true
  },
  close: {
    type: Function,
    default: () => {}
  },
  className: {
    type: String,
    default: ''
  }
})
const initialSlide = computed(() => {
  if (props.file && props.file.ossUrl) {
    return props.fileList.findIndex(item => item.ossUrl === props.file.ossUrl)
  }
  return 0
})

const state = reactive({
  previewSize: 100,
  file: props.file,
  boxWidth: null,
  activeIndex: initialSlide.value,
  fileList: props.fileList,
  isSupportWebp: false,
  imgWidth: [],
  width: 520,
  x: window.innerWidth * 0.5 - 260,
  y: window.innerHeight * 0.1,
  height: window.innerHeight * 0.8
})
const vDrag = {
  beforeMount: el => {
    let direc = '',
      resizeable = false,
      clientX = 0,
      clientY = 0
    const getDirection = function (ev) {
      let xP, yP, offset, dir
      dir = ''

      xP = ev.offsetX
      yP = ev.offsetY
      offset = 25

      if (yP < offset) dir += 'n'
      else if (yP > el.offsetHeight - offset - 40) dir += 's'
      if (xP < offset) dir += 'w'
      else if (xP > el.offsetWidth - offset) dir += 'e'

      return dir
    }
    // 在元素上做些操作
    el.onmousedown = function (e) {
      if (e.target.nodeName === 'INPUT') {
        return
      }
      const input = document.getElementById('input')
      input.blur()
      e.preventDefault()
      e.stopPropagation()
      const size = +e.currentTarget.dataset.size
      const nodeName = e.currentTarget.nodeName
      const disx = e.clientX - el.offsetLeft
      const disy = e.clientY - el.offsetTop
      // 鼠标按下时
      direc = getDirection(e)
      if (direc !== '') {
        resizeable = true
        el.style.cursor = ['e', 'w'].includes(direc)
          ? 'col-resize'
          : 'row-resize'
        clientX = e.clientX
        clientY = e.clientY
      }
      document.onmousemove = function (e) {
        const dir = getDirection(e)
        let cursor
        if (dir === '') cursor = 'default'
        else cursor = dir + '-resize'
        // 修改鼠标显示效果
        el.style.cursor = cursor
        let x = e.clientX - disx
        const y = e.clientY - disy
        if (!resizeable) {
          if (x >= window.innerWidth - el.offsetWidth) {
            x = window.innerWidth - el.offsetWidth
          }
          el.style.left = x + 'px'
          el.style.top = y + 'px'
          el.style.transform =
            nodeName === 'IMG'
              ? `scale3d(${size / 100},${size / 100},1)`
              : 'unset'
        } else {
          if (direc.indexOf('e') > -1) {
            el.style.width = Math.max(520, e.clientX - el.offsetLeft) + 'px'
          }
          if (direc.indexOf('w') > -1) {
            el.style.width =
              Math.max(520, clientX - e.clientX + el.offsetWidth) + 'px'
            el.offsetWidth > 520 && (el.style.left = e.clientX - 260 + 'px')
            clientX = e.clientX
          }
          if (direc.indexOf('n') > -1) {
            el.style.height =
              Math.max(600, clientY - e.clientY + el.offsetHeight) + 'px'
            el.offsetHeight > 700 && (el.style.top = e.clientY + 'px')
            clientY = e.clientY
          }
          if (direc.indexOf('s') > -1) {
            el.style.height = Math.max(600, e.clientY - el.offsetTop) + 'px'
          }
        }
      }
      document.onmouseup = function () {
        resizeable = false
        document.onmousemove = document.onmouseup = null
      }
    }
  }
}
const emits = defineEmits(['update:visible'])
const afterChange = baseIndex => {
  state.previewSize = 100
  if (baseIndex === -1) {
    if (state.activeIndex === 0) {
      state.activeIndex = state.fileList.length - 1
    } else {
      state.activeIndex = state.activeIndex + baseIndex
    }
  } else {
    if (state.activeIndex === state.fileList.length - 1) {
      state.activeIndex = 0
    } else {
      state.activeIndex = state.activeIndex + baseIndex
    }
  }
}
const onClose = () => {
  if (props.close) {
    props.close()
  }
  emits('update:visible', false)
}
const increase = () => {
  state.previewSize = +state.previewSize + 10
  // state.width = state.width * (state.previewSize / 100)
  // state.height = state.height * (state.previewSize / 100)
}
const decline = () => {
  state.previewSize = +state.previewSize - 10
  // state.width = state.width * 0.9
  // state.height = state.height * 0.9
}
</script>
<style lang="scss" scoped>
.ant-modal-wrap1 {
  z-index: 1000 !important;
}
.vdr-container.active {
  border-color: #fefefe;
  border-style: solid;
}
.preview {
  position: relative;
  .img-modal {
    height: 100%;
    width: 100%;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    color: rgba(0, 0, 0, 0.85);
    font-size: 14px;
    font-variant: tabular-nums;
    line-height: 1.5715;
    list-style: none;
    font-feature-settings: 'tnum';
    position: relative;
    margin: 0 auto;
    /* padding-bottom: 24px;
    pointer-events: none; */
  }

  .ant-modal-content,
  .ant-modal-body {
    height: 100%;
    header {
      height: 40px;
      line-height: 40px;
      padding: 0 16px;
      border-bottom: 1px solid #eaeaea;
    }
  }
  &-action {
    display: flex;
    align-items: center;
  }
  .preview_img_wrapper {
    overflow: hidden;
    position: relative;
    height: calc(100% - 40px);
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #fafafa;
    .slick-prev {
      left: 25px;
    }

    .custom-slick-arrow {
      font-size: 14px;
      color: #333;
      width: 25px;
      line-height: 50px;
      text-align: center;
      z-index: 101;
      height: 50px;
      right: 0;
      background-color: hsla(0, 0%, 100%, 0.6);
      position: absolute;
      top: 50%;
      padding: 0;
      transform: translateY(-50%);
      cursor: pointer;
      &.slick-next {
        right: 25px;
      }
    }
  }
  .view_img {
    &_list {
      width: 100%;
      transition: all 0.3s;
      text-align: center;
      position: relative;
      z-index: 100;
      width: 100%;
      margin: 0 auto;
    }
    &_item {
      width: 100%;
      height: 100%;
      opacity: 0;
      z-index: 100;
      position: absolute;
      top: 0;
      visibility: hidden;
      text-align: center;
      transition: all 0.3s cubic-bezier(0.215, 0.61, 0.355, 1) 0s;
      img {
        max-width: 100%;
        max-height: 100%;
        width: auto;
        height: auto;
        position: relative;
      }
      &.active {
        opacity: 1;
        visibility: visible;
        position: relative;
      }
    }
  }
}
</style>
